package com.weitu.contractor.controller;

import com.weitu.accessory.service.AccessoryUtilService;
import com.weitu.accessory.util.AccessoryUtil;
import com.weitu.base.annotaion.SystemLog;
import com.weitu.base.controller.BaseController;
import com.weitu.contractor.entity.ContractorEvaluation;
import com.weitu.contractor.entity.ContractorEvaluationCriteria;
import com.weitu.contractor.entity.ContractorExposure;
import com.weitu.contractor.service.ContractorAuditService;
import com.weitu.contractor.service.ContractorEvaluationService;
import com.weitu.contractor.service.ContractorExposureService;
import com.weitu.paging.DataGridPagination;
import com.weitu.permission.dataAuthority.service.DataAuthorityService;
import com.weitu.plugin.PageView;
import com.weitu.util.AjaxResult;
import com.weitu.util.DateTimeUtil;
import com.weitu.util.IDGenerator;
import com.weitu.workflow.definition.constant.FlowDefConstants;
import com.weitu.workflow.flowBusiness.constant.FlowBusinessConstants;
import com.weitu.workflow.flowManagement.entity.WorkflowReview;
import com.weitu.workflow.flowManagement.service.FlowManagementService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.fireflow.kernel.KernelException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.weitu.util.AjaxResult.fail;
import static com.weitu.util.AjaxResult.success;

/**
 * @author LiMeng 2017/4/26
 */
@Controller
@RequestMapping(value = "contractor/annualEvaluation")
public class AnnualEvaluationController extends BaseController {
    private static final String MODULE_BATH_PATH = BASE_JSP_PATH + "contractor/annualEvaluation";
    private final ContractorEvaluationService contractorEvaluationService;
    private final ContractorExposureService contractorExposureService;
    private final ContractorAuditService contractorAuditService;
    private final FlowManagementService flowManagementService;
    private final DataAuthorityService dataAuthorityService;
    private final AccessoryUtilService accessoryUtilService;

    @Autowired
    public AnnualEvaluationController(ContractorEvaluationService contractorEvaluationService
            , ContractorExposureService contractorExposureService
            , ContractorAuditService contractorAuditService
            , FlowManagementService flowManagementService
            , DataAuthorityService dataAuthorityService
            , AccessoryUtilService accessoryUtilService) {
        this.contractorEvaluationService = contractorEvaluationService;
        this.contractorExposureService = contractorExposureService;
        this.contractorAuditService = contractorAuditService;
        this.flowManagementService = flowManagementService;
        this.dataAuthorityService = dataAuthorityService;
        this.accessoryUtilService = accessoryUtilService;
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list() {
        return MODULE_BATH_PATH + "/list";
    }

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add(Model model) {
        model.addAttribute("loginUserId", getSessionUser().getId());
        model.addAttribute("loginUserName", getSessionUser().getRealName());
        model.addAttribute("today", DateFormatUtils.ISO_DATE_FORMAT.format(new Date()));
        return MODULE_BATH_PATH + "/add";
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String edit(Model model, String id) {
        if (StringUtils.isNotEmpty(getPara("businessId"))) {
            id = getPara("businessId");
            WorkflowReview workflowReview = this.flowManagementService.queryWorkflowReviewByWorkItemId(getPara("workItemId"));
            model.addAttribute("workflowReview", workflowReview);
        }
        putModelAttributes(model, id);
        return MODULE_BATH_PATH + "/edit";
    }

    @RequestMapping(value = "/view", method = RequestMethod.GET)
    public String view(Model model, String id) {
        putModelAttributes(model, id);
        return MODULE_BATH_PATH + "/edit";
    }

    @ResponseBody
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public Object listAjax(HttpServletRequest request, String sort) throws Exception {
        ContractorEvaluationCriteria criteria = new ContractorEvaluationCriteria();
        ContractorEvaluationCriteria.Criteria cr = criteria.createCriteria()
                .andDelStateEqualTo(0)
                .andEvaluateTypeEqualTo(0);
        putSearchCriteria(cr);

        int count = contractorEvaluationService.countByCriteria(criteria);

        DataGridPagination dataGridPagination = DataGridPagination.getInstance(request, count);//获取分页对象
        PageView pageView = dataGridPagination.getPageView();//生成pageView分页对象
        //未传sort参数是采用添加时间排序
        if (StringUtils.isEmpty(sort)) {
            pageView.setSortColumn("addTime");
        } else {
            criteria.setOrderByClause(pageView.getSortColumn() + " " + pageView.getOrderType());
        }
        criteria.setPageView(pageView);

        List<ContractorEvaluation> contractorEvaluations = contractorEvaluationService.selectByCriteria(criteria);

        return dataGridPagination.flushDataGridData(contractorEvaluations);
    }

    @SystemLog(module = "年度评价", methods = "新增承包商年度评价信息")
    @ResponseBody
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @Transactional
    public AjaxResult addAjax(ContractorEvaluation contractorEvaluation, String exposureStartDate, String exposureEndDate) throws Exception {
        if (contractorEvaluationService.checkIfExist(contractorEvaluation.getContractorAuditId(),
                contractorEvaluation.getYear()
                , contractorEvaluation.getEvaluateType())) {
            return fail("已存在相同数据，请重新选择！");
        }

        String id = IDGenerator.getId();
        contractorEvaluation.setId(id);
        contractorEvaluation.setAddUserId(getSessionUser().getId());
        contractorEvaluation.setAddDeptId(getSessionUser().getDepartment().getId());
        contractorEvaluation.setAddTime(DateTimeUtil.formatterDateTime());

        if (contractorEvaluation.getIsExposure() == 1) {
            if (contractorExposureService.checkIfExist(contractorEvaluation.getContractorAuditId(), exposureEndDate)) {
                return fail("曝光时间内已有该承包商，请重新选择！");
            }
            String exposureId = IDGenerator.getId();
            if (insertContractorExposure(exposureId, contractorEvaluation.getContractorAuditId(), exposureStartDate, exposureEndDate)) {
                contractorEvaluation.setExposureId(exposureId);
                if (AccessoryUtil.saveAccerssoryInfo(id)) {
                    if (contractorEvaluationService.insertSelective(contractorEvaluation) > 0) {
                        return success("保存成功！", contractorEvaluation);
                    }
                    return fail("保存失败！");
                }
                return fail("附件信息保存失败！");
            }
            return fail("保存失败！");
        }

        if (AccessoryUtil.saveAccerssoryInfo(id)) {
            if (contractorEvaluationService.insertSelective(contractorEvaluation) > 0) {
                return success("保存成功！", contractorEvaluation);
            }
            return fail("保存失败！");
        }
        return fail("附件信息保存失败！");
    }

    @SystemLog(module = "年度评价", methods = "更新承包商年度评价信息")
    @ResponseBody
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @Transactional
    public AjaxResult editAjax(ContractorEvaluation contractorEvaluation) throws Exception {
        if (contractorEvaluationService.checkIfExist(contractorEvaluation.getContractorAuditId(),
                contractorEvaluation.getYear(),
                contractorEvaluation.getEvaluateType(),
                contractorEvaluation.getId())) {
            return fail("已存在相同数据，请重新选择！");
        }

        contractorEvaluation.setUpdateUserId(getSessionUser().getId());
        contractorEvaluation.setUpdateDeptId(getSessionUser().getDepartment().getId());
        contractorEvaluation.setUpdateTime(DateTimeUtil.formatterDateTime());

        if (AccessoryUtil.saveAccerssoryInfo(contractorEvaluation.getId())) {
            if (contractorEvaluationService.updateByPrimaryKeySelective(contractorEvaluation) > 0) {
                return success("保存成功！", contractorEvaluation);
            }
            return fail("保存失败！");
        }
        return fail("附件信息保存失败！");
    }

    @SystemLog(module = "年度评价", methods = "删除承包商年度评价信息")
    @ResponseBody
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public AjaxResult deleteAjax(String id) throws Exception {
        if (contractorEvaluationService.deleteByPrimaryKey(id) > 0) {
            return success("删除成功！");
        } else {
            return fail("删除失败！");
        }
    }

    @SystemLog(module = "年度评价", methods = "提交年度评价审核信息")
    @ResponseBody
    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    public AjaxResult submitAjax(ContractorEvaluation contractorEvaluation, String nextUserId) throws Exception {
        if (contractorEvaluationService.checkIfExist(contractorEvaluation.getContractorAuditId(),
                contractorEvaluation.getYear(),
                contractorEvaluation.getEvaluateType(),
                contractorEvaluation.getId())) {
            return fail("已存在相同数据，请重新选择！");
        }

        contractorEvaluation.setUpdateUserId(getSessionUser().getId());
        contractorEvaluation.setUpdateDeptId(getSessionUser().getDepartment().getId());
        contractorEvaluation.setUpdateTime(DateTimeUtil.formatterDateTime());
        contractorEvaluation.setAuditState(1);
        if (AccessoryUtil.saveAccerssoryInfo(contractorEvaluation.getId())) {
            if (contractorEvaluationService.updateByPrimaryKeySelective(contractorEvaluation) > 0) {
                handleFlowStart(contractorEvaluation, nextUserId);
                return success("提交成功！", contractorEvaluation);
            }
            return fail("提交失败！");
        }
        return fail("附件信息保存失败！");
    }

    @SystemLog(module = "年度评价", methods = "审核年度评价信息")
    @ResponseBody
    @RequestMapping(value = "/audit", method = RequestMethod.POST)
    public AjaxResult auditAjax(HttpServletRequest request) throws Exception {
        if (handleFlowEnd(request)) {
            return success("审批成功！");
        }
        return fail("审批失败！");
    }

    /**
     * 向页面实体添加属性
     *
     * @param model 页面实体
     * @param id    主键id
     */
    private void putModelAttributes(Model model, String id) {
        ContractorEvaluation contractorEvaluation = contractorEvaluationService.selectByPrimaryKey(id);
        ContractorExposure contractorExposure = contractorExposureService.selectByPrimaryKey(contractorEvaluation.getExposureId());

        model.addAttribute("accessoryList", accessoryUtilService.queryAccessoryByBusinessId(id));
        model.addAttribute("contractorEvaluation", contractorEvaluation);
        model.addAttribute("contractorExposure", contractorExposure);
        model.addAttribute("loginUserId", getSessionUser().getId());
    }

    /**
     * 插入承包商曝光台数据
     *
     * @param contractorAuditId 承包商资质id
     * @param exposureStartDate 曝光开始日期
     * @param exposureEndDate   曝光结束日期
     * @return 是否成功
     * @throws Exception 异常
     */
    private boolean insertContractorExposure(String id, String contractorAuditId, String exposureStartDate, String exposureEndDate) throws Exception {
        ContractorExposure contractorExposure = new ContractorExposure();
        contractorExposure.setContractorAuditId(contractorAuditId);
        contractorExposure.setExposureStartDate(exposureStartDate);
        contractorExposure.setExposureEndDate(exposureEndDate);
        contractorExposure.setApplicantId(getSessionUser().getId());
        contractorExposure.setApplicantDate(DateFormatUtils.ISO_DATE_FORMAT.format(new Date()));
        contractorExposure.setId(id);
        contractorExposure.setAddUserId(getSessionUser().getId());
        contractorExposure.setAddDeptId(getSessionUser().getDepartment().getId());
        contractorExposure.setAddTime(DateTimeUtil.formatterDateTime());
        return contractorExposureService.insertSelective(contractorExposure) > 0;
    }

    /**
     * 添加查询条件
     *
     * @param criteria 条件
     */
    private void putSearchCriteria(ContractorEvaluationCriteria.Criteria criteria) {
        if (StringUtils.isNotEmpty(getPara("contractorName"))) {
            List<String> contractorAuditIds = contractorAuditService.selectContractorAuditIdsByName(getPara("contractorName"));
            if (!contractorAuditIds.isEmpty()) {
                criteria.andContractorAuditIdIn(contractorAuditIds);
            } else {
                criteria.andIdIsNull();
            }
        }
        if (StringUtils.isNotEmpty(getPara("isQualified"))) {
            criteria.andIsQualifiedEqualTo(getParaToInt("isQualified"));
        }
        if (StringUtils.isNotEmpty(getPara("isExposure"))) {
            criteria.andIsExposureEqualTo(getParaToInt("isExposure"));
        }
        if (StringUtils.isNotEmpty(getPara("year"))) {
            criteria.andYearEqualTo(getParaToInt("year"));
        }
        if (StringUtils.isNotEmpty(getPara("evaluatorId"))) {
            criteria.andEvaluatorIdEqualTo(getPara("evaluatorId"));
        }
        if (StringUtils.isNotEmpty(getPara("addTimeMin"))) {
            criteria.andAddTimeGreaterThanOrEqualTo(getPara("addTimeMin"));
        }
        if (StringUtils.isNotEmpty(getPara("addTimeMax"))) {
            criteria.andAddTimeLessThanOrEqualTo(getPara("addTimeMax"));
        }
        if (StringUtils.isNotEmpty(getPara("evaluateDateMin"))) {
            criteria.andEvaluateDateGreaterThanOrEqualTo(getPara("evaluateDateMin"));
        }
        if (StringUtils.isNotEmpty(getPara("evaluateDateMax"))) {
            criteria.andEvaluateDateLessThanOrEqualTo(getPara("evaluateDateMax"));
        }
        if (StringUtils.isNotEmpty(getPara("addUserId"))) {
            criteria.andAddUserIdEqualTo(getPara("addUserId"));
        }
        if (StringUtils.isNotEmpty(getPara("addDeptId"))) {
            criteria.andAddDeptIdEqualTo(getPara("addDeptId"));
        }
        if (StringUtils.isNotEmpty(getPara("auditState"))) {
            criteria.andAuditStateEqualTo(getParaToInt("auditState"));
        }
        List<String> deptIds = dataAuthorityService.selectDataDeptIdByUserIdAndDeptId(getSessionUser().getId()
                , getSessionUser().getDepartment().getId());
        if (!deptIds.isEmpty()) {
            criteria.andAddDeptIdIn(deptIds);
        }
    }

    /**
     * 处理工作流开始
     *
     * @param contractorEvaluation 参数实体
     * @param nextUserId           下个处理人id
     * @throws Exception 异常
     */
    private void handleFlowStart(ContractorEvaluation contractorEvaluation, String nextUserId) throws Exception {
        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put(FlowDefConstants.FLOW_FIRSTUSER_ID, nextUserId);
        String content = "年度评价流程";
        //启动流程实例
        flowManagementService.flowCreateAndRun(FlowBusinessConstants.BUSINESS_ANNUAL_EVALUATION
                , contractorEvaluation.getId()
                , content
                , getSessionUser().getName()
                , dataMap);
    }

    /**
     * 处理工作流结束
     *
     * @param request 请求
     * @throws KernelException 内核异常
     */
    private boolean handleFlowEnd(HttpServletRequest request) throws KernelException, NumberFormatException {
        String workItemId = request.getParameter("workItemId");//获取工作项id
        //查询处理结果及意见
        WorkflowReview workflowReview = flowManagementService.getWorkflowReviewByRequest(request, "workflowReview", workItemId);
        //保存处理结果
        boolean boo = flowManagementService.saveWorkflowReview(workflowReview);

        //结束环节，继续流程向下执行
        if (boo) {
            flowManagementService.workItemComplete(workItemId);
            int auditState = Integer.parseInt(request.getParameter("auditState").trim());
            ContractorEvaluation contractorEvaluation = new ContractorEvaluation();
            contractorEvaluation.setId(request.getParameter("businessId"));
            contractorEvaluation.setAuditState(auditState);
            contractorEvaluationService.updateByPrimaryKeySelective(contractorEvaluation);
            return true;
        }
        return false;
    }
}
